// Focus Tide - 专注潮汐应用
// 所有 Tauri 命令和逻辑都在这个文件中

use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use tauri::{AppHandle, Manager, Window, WebviewWindowBuilder, WebviewUrl, Emitter};
use tokio::time::sleep;

// ==================== 数据模型 ====================

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Settings {
    pub work_duration: u32,        // 工作时长（分钟）
    pub break_duration: u32,       // 休息时长（分钟）
    pub distraction_apps: Vec<String>, // 分心应用列表
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            work_duration: 25,
            break_duration: 5,
            distraction_apps: vec![
                "bilibili".to_string(),
                "抖音".to_string(),
                "微博".to_string(),
                "YouTube".to_string(),
                "Twitter".to_string(),
            ],
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct TimerState {
    remaining: u32,        // 剩余时间（秒）
    is_running: bool,
    is_paused: bool,
    #[serde(skip)] // Instant 不能直接序列化，前端也不需要
    start_time: Option<Instant>,
    paused_duration: u32, // 已暂停的累计时间（秒）
}

impl Default for TimerState {
    fn default() -> Self {
        TimerState {
            remaining: 25 * 60,
            is_running: false,
            is_paused: false,
            start_time: None,
            paused_duration: 0,
        }
    }
}

// ==================== 全局状态 ====================

struct AppState {
    timer: Arc<Mutex<TimerState>>,
    settings: Arc<Mutex<Settings>>,
    #[allow(dead_code)]
    overlay_window: Arc<Mutex<Option<Window>>>,
    monitor_running: Arc<Mutex<bool>>,
    should_show_water: Arc<Mutex<bool>>, // 是否应该显示水浸动画
}

// ==================== 计时器相关命令 ====================

#[tauri::command]
async fn start_timer(
    duration: u32,
    app: AppHandle,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut timer = state.timer.lock().unwrap();
    timer.remaining = duration;
    timer.is_running = true;
    timer.is_paused = false;
    timer.start_time = Some(Instant::now());
    timer.paused_duration = 0;

    // 启动窗口监控
    start_window_monitor(app.clone(), state.clone())?;

    // 启动计时器循环
    let app_clone = app.clone();
    let timer_clone = state.timer.clone();
    // 使用 Tauri 的异步运行时
    tauri::async_runtime::spawn(async move {
        timer_loop(app_clone, timer_clone).await;
    });

    // 立即发送一次状态更新
    app.emit("timer-tick", serde_json::json!({ "remaining": timer.remaining })).map_err(|e| e.to_string())?;

    Ok(())
}

#[tauri::command]
async fn pause_timer(
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut timer = state.timer.lock().unwrap();
    if timer.is_running {
        timer.is_paused = true;
        timer.is_running = false;
        if let Some(start) = timer.start_time {
            timer.paused_duration += start.elapsed().as_secs() as u32;
        }
    }
    Ok(())
}

#[tauri::command]
async fn resume_timer(
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut timer = state.timer.lock().unwrap();
    if timer.is_paused {
        timer.is_paused = false;
        timer.is_running = true;
        timer.start_time = Some(Instant::now());
    }
    Ok(())
}

#[tauri::command]
async fn reset_timer(
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut timer = state.timer.lock().unwrap();
    *timer = TimerState::default();
    Ok(())
}

#[tauri::command]
async fn get_remaining_time(
    state: tauri::State<'_, AppState>,
) -> Result<u32, String> {
    let timer = state.timer.lock().unwrap();
    Ok(timer.remaining)
}

#[tauri::command]
async fn get_timer_status(
    state: tauri::State<'_, AppState>,
) -> Result<TimerState, String> {
    let timer = state.timer.lock().unwrap();
    Ok(timer.clone())
}

async fn timer_loop(app: AppHandle, timer: Arc<Mutex<TimerState>>) {
    loop {
        sleep(Duration::from_secs(1)).await;

        let mut timer_guard = timer.lock().unwrap();
        
        if !timer_guard.is_running {
            break;
        }

        if let Some(start) = timer_guard.start_time {
            let elapsed = start.elapsed().as_secs() as u32 + timer_guard.paused_duration;
            if elapsed >= timer_guard.remaining {
                timer_guard.remaining = 0;
                timer_guard.is_running = false;
                
                // 发送完成事件
                let _ = app.emit("timer-complete", ());
                
                // 停止窗口监控
                let _ = stop_window_monitor(&app);
                
                break;
            } else {
                timer_guard.remaining -= 1;
            }
        }

        // 发送时间更新事件
        let remaining = timer_guard.remaining;
        drop(timer_guard);
        
        let _ = app.emit("timer-tick", serde_json::json!({ "remaining": remaining }));
    }
}

// ==================== 设置相关命令 ====================

#[tauri::command]
async fn get_settings(
    state: tauri::State<'_, AppState>,
) -> Result<Settings, String> {
    let settings = state.settings.lock().unwrap();
    Ok(settings.clone())
}

#[tauri::command]
async fn save_settings(
    work_duration: u32,
    break_duration: u32,
    distraction_apps: Vec<String>,
    app: AppHandle,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut settings = state.settings.lock().unwrap();
    settings.work_duration = work_duration;
    settings.break_duration = break_duration;
    settings.distraction_apps = distraction_apps;

    // 保存到文件
    save_settings_to_file(&app, &settings)?;

    Ok(())
}

fn load_settings_from_file(app: &AppHandle) -> Result<Settings, String> {
    use std::fs;
    use tauri::path::BaseDirectory;

    let app_data = app.path()
        .resolve("settings.json", BaseDirectory::AppData)
        .map_err(|e| format!("无法获取应用数据目录: {}", e))?;

    if app_data.exists() {
        let content = fs::read_to_string(&app_data)
            .map_err(|e| format!("读取设置文件失败: {}", e))?;
        serde_json::from_str(&content)
            .map_err(|e| format!("解析设置文件失败: {}", e))
    } else {
        Ok(Settings::default())
    }
}

fn save_settings_to_file(app: &AppHandle, settings: &Settings) -> Result<(), String> {
    use std::fs;
    use tauri::path::BaseDirectory;

    let app_data_dir = app.path()
        .resolve(".", BaseDirectory::AppData)
        .map_err(|e| format!("无法获取应用数据目录: {}", e))?;
    
    fs::create_dir_all(&app_data_dir)
        .map_err(|e| format!("创建应用数据目录失败: {}", e))?;

    let settings_path = app.path()
        .resolve("settings.json", BaseDirectory::AppData)
        .map_err(|e| format!("无法获取设置文件路径: {}", e))?;
    
    let content = serde_json::to_string_pretty(settings)
        .map_err(|e| format!("序列化设置失败: {}", e))?;
    fs::write(&settings_path, content)
        .map_err(|e| format!("保存设置文件失败: {}", e))?;

    Ok(())
}

// ==================== 窗口监控相关命令 ====================

#[tauri::command]
async fn get_water_animation_state(
    state: tauri::State<'_, AppState>,
) -> Result<bool, String> {
    let should_show = state.should_show_water.lock().unwrap();
    Ok(*should_show)
}

#[tauri::command]
async fn get_active_window_name() -> Result<Option<String>, String> {
    #[cfg(target_os = "windows")]
    {
        check_active_window_windows()
    }
    
    #[cfg(target_os = "macos")]
    {
        check_active_window_macos()
    }
    
    #[cfg(not(any(target_os = "windows", target_os = "macos")))]
    {
        Ok(None)
    }
}

#[tauri::command]
async fn get_running_apps() -> Result<Vec<String>, String> {
    #[cfg(target_os = "windows")]
    {
        get_running_apps_windows()
    }
    
    #[cfg(target_os = "macos")]
    {
        get_running_apps_macos()
    }
    
    #[cfg(not(any(target_os = "windows", target_os = "macos")))]
    {
        Ok(vec![])
    }
}

#[cfg(target_os = "windows")]
fn get_running_apps_windows() -> Result<Vec<String>, String> {
    use winapi::um::winuser::{EnumWindows, GetWindowTextW, GetWindowTextLengthW, IsWindowVisible};
    use winapi::shared::minwindef::{BOOL, LPARAM, TRUE};
    use winapi::shared::windef::HWND;
    use std::ffi::OsString;
    use std::os::windows::ffi::OsStringExt;

    unsafe extern "system" fn enum_window_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
        if IsWindowVisible(hwnd) == 0 {
            return TRUE;
        }

        let len = GetWindowTextLengthW(hwnd);
        if len > 0 {
            let mut buf = vec![0u16; (len + 1) as usize];
            let len = GetWindowTextW(hwnd, buf.as_mut_ptr(), buf.len() as i32);
            if len > 0 {
                let title = OsString::from_wide(&buf[..len as usize]).to_string_lossy().into_owned();
                if !title.is_empty() {
                    let apps = &mut *(lparam as *mut Vec<String>);
                    if !apps.contains(&title) {
                        apps.push(title);
                    }
                }
            }
        }
        TRUE
    }

    let mut apps: Vec<String> = Vec::new();
    unsafe {
        EnumWindows(Some(enum_window_proc), &mut apps as *mut _ as LPARAM);
    }
    Ok(apps)
}

#[cfg(target_os = "macos")]
fn get_running_apps_macos() -> Result<Vec<String>, String> {
    use objc::runtime::{Class, Object};
    use objc::{msg_send, sel, sel_impl};

    unsafe {
        let workspace_class = Class::get("NSWorkspace").ok_or("无法获取 NSWorkspace")?;
        let workspace: *mut Object = msg_send![workspace_class, sharedWorkspace];
        let apps: *mut Object = msg_send![workspace, runningApplications];
        
        let count: usize = msg_send![apps, count];
        let mut result = Vec::new();

        for i in 0..count {
            let app: *mut Object = msg_send![apps, objectAtIndex: i];
            // 检查是否是普通应用 (ActivationPolicyRegular)
            let policy: isize = msg_send![app, activationPolicy];
            if policy == 0 { // NSApplicationActivationPolicyRegular = 0
                 let name: *mut Object = msg_send![app, localizedName];
                 if !name.is_null() {
                     let c_str = std::ffi::CStr::from_ptr(msg_send![name, UTF8String] as *const i8);
                     result.push(c_str.to_string_lossy().to_string());
                 }
            }
        }
        Ok(result)
    }
}

#[cfg(target_os = "windows")]
fn check_active_window_windows() -> Result<Option<String>, String> {
    use winapi::um::winuser::{GetForegroundWindow, GetWindowThreadProcessId, GetWindowTextW, GetWindowTextLengthW};
    use winapi::um::processthreadsapi::OpenProcess;
    use winapi::um::psapi::GetModuleFileNameExA;
    use winapi::um::winnt::{PROCESS_QUERY_INFORMATION, PROCESS_VM_READ};
    use std::ptr;

    unsafe {
        let hwnd = GetForegroundWindow();
        if hwnd.is_null() {
            return Ok(None);
        }

        let mut process_id: u32 = 0;
        GetWindowThreadProcessId(hwnd, &mut process_id);

        let handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, process_id);
        
        let exe_name = if !handle.is_null() {
            let mut filename = vec![0u8; 260];
            let len = GetModuleFileNameExA(handle, ptr::null_mut(), filename.as_mut_ptr() as *mut i8, filename.len() as u32);
            winapi::um::handleapi::CloseHandle(handle);

            if len > 0 {
                let path = String::from_utf8_lossy(&filename[..len as usize]);
                std::path::Path::new(path.as_ref())
                    .file_name()
                    .and_then(|n| n.to_str())
                    .map(|s| s.to_string())
                    .unwrap_or_default()
            } else {
                String::new()
            }
        } else {
            String::new()
        };

        // 获取窗口标题
        let len = GetWindowTextLengthW(hwnd);
        let title = if len > 0 {
            let mut buf = vec![0u16; (len + 1) as usize];
            let len = GetWindowTextW(hwnd, buf.as_mut_ptr(), buf.len() as i32);
            String::from_utf16_lossy(&buf[..len as usize])
        } else {
            String::new()
        };

        if exe_name.is_empty() && title.is_empty() {
            Ok(None)
        } else {
            // 返回 "标题 | exe名" 的组合，以便同时匹配两者
            Ok(Some(format!("{} | {}", title, exe_name)))
        }
    }
}

#[cfg(target_os = "macos")]
fn check_active_window_macos() -> Result<Option<String>, String> {
    use objc::runtime::{Class, Object};
    use objc::{msg_send, sel, sel_impl};

    unsafe {
        let workspace_class = Class::get("NSWorkspace").ok_or("无法获取 NSWorkspace")?;
        let workspace: *mut Object = msg_send![workspace_class, sharedWorkspace];
        
        let front_app: *mut Object = msg_send![workspace, frontApplication];
        if front_app.is_null() {
            return Ok(None);
        }

        let bundle_id: *mut Object = msg_send![front_app, bundleIdentifier];
        if bundle_id.is_null() {
            return Ok(None);
        }

        let bundle_id_str: *mut Object = msg_send![bundle_id, UTF8String];
        if bundle_id_str.is_null() {
            return Ok(None);
        }

        let c_str = std::ffi::CStr::from_ptr(bundle_id_str as *const i8);
        let app_name = c_str.to_string_lossy().to_string();
        Ok(Some(app_name))
    }
}

fn start_window_monitor(
    app: AppHandle,
    state: tauri::State<'_, AppState>,
) -> Result<(), String> {
    let mut monitor_running = state.monitor_running.lock().unwrap();
    if *monitor_running {
        return Ok(());
    }
    *monitor_running = true;
    drop(monitor_running);

    let app_clone = app.clone();
    let timer = state.timer.clone();
    let settings = state.settings.clone();
    let monitor = state.monitor_running.clone();
    let should_show_water = state.should_show_water.clone();
    
    // 使用 Tauri 的异步运行时
    tauri::async_runtime::spawn(async move {
        window_monitor_loop(app_clone, timer, settings, monitor, should_show_water).await;
    });

    Ok(())
}

fn stop_window_monitor(_app: &AppHandle) -> Result<(), String> {
    // 通过事件通知监控循环停止
    // 实际上我们使用的是共享状态 monitor_running，所以只需要在这里处理可能的清理工作
    // 如果需要主动通知前端，可以在这里 emit 事件
    // let _ = app.emit("monitor-stopped", ());
    Ok(())
}

async fn window_monitor_loop(
    app: AppHandle,
    timer: Arc<Mutex<TimerState>>,
    settings: Arc<Mutex<Settings>>,
    monitor: Arc<Mutex<bool>>,
    should_show_water: Arc<Mutex<bool>>,
) {
    println!("窗口监控循环已启动");
    loop {
        sleep(Duration::from_secs(1)).await;

        // 检查监控是否还在运行
        {
            let monitor_running = monitor.lock().unwrap();
            if !*monitor_running {
                println!("监控标志位为 false，停止监控");
                break;
            }
        }

        // 检查计时器是否还在运行
        let should_stop = {
            let timer_guard = timer.lock().unwrap();
            !timer_guard.is_running
        };

        if should_stop {
            println!("计时器未运行，停止监控");
            // 确保计时器停止时关闭覆盖窗口
            let _ = close_overlay_window(app.clone()).await;
            break;
        }

        // 检查活动窗口
        match get_active_window_name().await {
            Ok(Some(app_name)) => {
                // 如果是覆盖窗口自己，则忽略（避免自己抢焦点导致循环）
                if app_name.contains("Focus Tide Overlay") {
                    continue;
                }

                // println!("当前活动窗口: {}", app_name); // 调试日志

                let is_distraction = {
                    let settings_guard = settings.lock().unwrap();
                    settings_guard.distraction_apps.iter()
                        .any(|distraction| {
                            let matched = app_name.to_lowercase().contains(&distraction.to_lowercase());
                            if matched {
                                println!("检测到分心应用: {} (匹配规则: {})", app_name, distraction);
                            }
                            matched
                        })
                };

                // 更新状态
                let state_changed = {
                    let mut should_show = should_show_water.lock().unwrap();
                    if *should_show != is_distraction {
                        println!("状态变更: 显示水浸动画 = {}", is_distraction);
                        *should_show = is_distraction;
                        
                        // 发送状态变更事件
                        let _ = app.emit("water-animation-state", is_distraction);
                        
                        true
                    } else {
                        false
                    }
                };

                if state_changed {
                    if is_distraction {
                        let _ = create_overlay_window(app.clone()).await;
                    } else {
                        let _ = close_overlay_window(app.clone()).await;
                    }
                }
            }
            Ok(None) => {
                // println!("无法获取当前活动窗口名称");
            }
            Err(e) => {
                println!("获取活动窗口出错: {}", e);
            }
        }
    }
    println!("窗口监控循环已退出");
}

// ==================== 覆盖窗口相关命令 ====================

// 删除旧的 show_water_animation 和 hide_water_animation
// 因为现在使用 water-animation-state 事件驱动


#[tauri::command]
async fn create_overlay_window(
    app: AppHandle,
) -> Result<(), String> {
    #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
    {
        if let Some(window) = app.get_webview_window("overlay") {
            window.show().map_err(|e| e.to_string())?;
            // window.set_focus().map_err(|e| e.to_string())?;
            return Ok(());
        }

        let window = WebviewWindowBuilder::new(
            &app,
            "overlay",
            WebviewUrl::App("index.html".into()),
        )
        .title("Focus Tide Overlay")
        .transparent(true)
        .decorations(false)
        .always_on_top(true)
        .skip_taskbar(true)
        .maximized(true)
        .visible(false) // 初始不可见，防止白屏闪烁
        .build()
        .map_err(|e| format!("创建覆盖窗口失败: {}", e))?;

        // 设置鼠标穿透 (需要根据不同平台实现，这里仅作示例，Tauri 2 可能有直接 API)
        #[cfg(target_os = "windows")]
        {
            // window.set_ignore_cursor_events(true).map_err(|e| e.to_string())?;
            // 暂时注释，如果 set_ignore_cursor_events 不可用，需要手动实现
            // 但为了"水浸"效果，可能不需要完全穿透？如果只是动画，确实需要穿透
            // 如果用户点击水，是否应该有反应？通常是穿透。
            let _ = window.set_ignore_cursor_events(true);
        }
        
        #[cfg(target_os = "macos")]
        {
             let _ = window.set_ignore_cursor_events(true);
        }

        println!("覆盖窗口已创建");
    }
    Ok(())
}

#[tauri::command]
async fn close_overlay_window(
    app: AppHandle,
) -> Result<(), String> {
    #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
    if let Some(window) = app.get_webview_window("overlay") {
        // 使用 hide 而不是 close，避免销毁窗口，提高再次显示的性能
        window.hide().map_err(|e| e.to_string())?;
        println!("覆盖窗口已隐藏");
    }
    Ok(())
}

#[tauri::command]
async fn show_overlay_window(
    app: AppHandle,
) -> Result<(), String> {
    #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
    if let Some(window) = app.get_webview_window("overlay") {
        window.show().map_err(|e| e.to_string())?;
        // window.set_focus().map_err(|e| e.to_string())?;
        println!("覆盖窗口已显示");
    }
    Ok(())
}

#[cfg(target_os = "windows")]
#[allow(dead_code)]
fn set_window_transparent_windows(_window: &Window) -> Result<(), String> {
    // use winapi::um::winuser::{GetWindowLongPtrW, SetWindowLongPtrW, GWL_EXSTYLE, WS_EX_TRANSPARENT, WS_EX_LAYERED};
    // use winapi::shared::windef::HWND;
    
    // Tauri 2.x 中获取窗口句柄的方式
    // 暂时注释掉，等确认 API 后再实现
    // 在 Tauri 2.x 中，可能需要使用不同的方式获取窗口句柄
    // let hwnd: HWND = window.native_handle()
    //     .map_err(|e| format!("获取窗口句柄失败: {}", e))?;
    
    // unsafe {
    //     let style = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
    //     SetWindowLongPtrW(hwnd, GWL_EXSTYLE, style | WS_EX_TRANSPARENT as isize | WS_EX_LAYERED as isize);
    // }
    
    // 暂时跳过，等确认 API 后再实现
    Ok(())
}

#[cfg(target_os = "macos")]
fn set_window_transparent_macos(window: &Window) -> Result<(), String> {
    // Tauri 2.x 中可能需要使用不同的 API
    // 暂时注释掉，等确认 API 后再实现
    // window.set_ignores_mouse_events(true)
    //     .map_err(|e| format!("设置事件穿透失败: {}", e))?;
    
    Ok(())
}


// 已删除无用的 show_water_animation 和 hide_water_animation 函数


// ==================== 主函数 ====================

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    // 初始化应用状态
    let app_state = AppState {
        timer: Arc::new(Mutex::new(TimerState::default())),
        settings: Arc::new(Mutex::new(Settings::default())),
        overlay_window: Arc::new(Mutex::new(None)),
        monitor_running: Arc::new(Mutex::new(false)),
        should_show_water: Arc::new(Mutex::new(false)),
    };

    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .manage(app_state)
        .setup(|app| {
            // 加载设置
            if let Ok(settings) = load_settings_from_file(app.handle()) {
                let app_state = app.state::<AppState>();
                *app_state.settings.lock().unwrap() = settings;
            }
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![
            start_timer,
            pause_timer,
            resume_timer,
            reset_timer,
            get_remaining_time,
            get_timer_status,
            get_settings,
            save_settings,
            get_active_window_name,
            get_running_apps,
            get_water_animation_state,
            create_overlay_window,
            close_overlay_window,
            show_overlay_window,
        ])
        .on_window_event(|window, event| {
            if let tauri::WindowEvent::CloseRequested { .. } = event {
                if window.label() == "main" {
                    // 当主窗口关闭时，退出整个应用，确保后台监控线程也被终止
                    window.app_handle().exit(0);
                }
            }
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
